
package com.by.toolkit.utils;

import cn.hutool.core.net.Ipv4Util;
import cn.hutool.system.SystemUtil;
import com.by.toolkit.consts.ByContextConst;
import com.by.toolkit.platform.ByContext;
import org.apache.commons.lang3.StringUtils;

import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.Enumeration;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 请求id工具类
 *
 * @author YanBingHao
 * @since 2024/1/4
 */
public class RequestIdUtil {

    private static final AtomicInteger ATOMIC_INTEGER = new AtomicInteger();

    public RequestIdUtil() {
    }

    public static String requestStart() {
        String requestId = generateTraceId();
        return requestStart(requestId);
    }

    public static String requestStart(String requestId) {
        if (StringUtils.isBlank(requestId)) {
            return requestStart();
        }
        ByContext.put(ByContextConst.REQUEST_ID, requestId);
        return requestId;
    }

    public static void requestEnd() {
        ByContext.remove(ByContextConst.REQUEST_ID);
    }

    public static String generateTraceId() {
        return ipToHex(getServerIp()) +
                System.nanoTime() +
                getNextAutoNumber() +
                SystemUtil.getCurrentPID();
    }

    private static String getNextAutoNumber() {
        if (ATOMIC_INTEGER.incrementAndGet() >= 10000) {
            ATOMIC_INTEGER.set(0);
        }
        return String.format("%04d", ATOMIC_INTEGER.get());
    }

    public static String getServerIp() {
        String serverIp = Ipv4Util.LOCAL_IP;

        try {
            serverIp = InetAddress.getLocalHost().getHostAddress();
            Enumeration<NetworkInterface> netInterfaces = NetworkInterface.getNetworkInterfaces();

            while (netInterfaces.hasMoreElements()) {
                NetworkInterface ni = netInterfaces.nextElement();
                if (ni.getInetAddresses().hasMoreElements()) {
                    InetAddress ip = ni.getInetAddresses().nextElement();
                    if (!(ip instanceof Inet6Address)) {
                        serverIp = ip.getHostAddress();
                        if (!ip.isSiteLocalAddress() && !ip.isLoopbackAddress() && !ip.getHostAddress().contains(":")) {
                            serverIp = ip.getHostAddress();
                            break;
                        }
                    }
                }
            }

            return serverIp;
        } catch (Exception var4) {
            return serverIp;
        }
    }

    public static String ipToHex(String ipString) {
        Long[] ip = new Long[4];
        int pos1 = ipString.indexOf(".");
        int pos2 = ipString.indexOf(".", pos1 + 1);
        int pos3 = ipString.indexOf(".", pos2 + 1);
        ip[0] = Long.parseLong(ipString.substring(0, pos1));
        ip[1] = Long.parseLong(ipString.substring(pos1 + 1, pos2));
        ip[2] = Long.parseLong(ipString.substring(pos2 + 1, pos3));
        ip[3] = Long.parseLong(ipString.substring(pos3 + 1));
        return Long.toHexString(ip[0]) + Long.toHexString(ip[1]) + Long.toHexString(ip[2]) + Long.toHexString(ip[3]);
    }
}
